home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / util / libs / ttrender.lha / ttrender-2.0 / Developer / source / base / ftoutln.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-04-06  |  16.3 KB  |  657 lines

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftoutln.c                                                              */
  4. /*                                                                         */
  5. /*    FreeType outline management (body).                                  */
  6. /*                                                                         */
  7. /*  Copyright 1996-2001 by                                                 */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19.   /*************************************************************************/
  20.   /*                                                                       */
  21.   /* All functions are declared in freetype.h.                             */
  22.   /*                                                                       */
  23.   /*************************************************************************/
  24.  
  25.  
  26. #include <ft2build.h>
  27. #include FT_OUTLINE_H
  28. #include FT_INTERNAL_OBJECTS_H
  29.  
  30.  
  31.   /*************************************************************************/
  32.   /*                                                                       */
  33.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  34.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  35.   /* messages during execution.                                            */
  36.   /*                                                                       */
  37. #undef  FT_COMPONENT
  38. #define FT_COMPONENT  trace_outline
  39.  
  40.  
  41.   static
  42.   const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
  43.  
  44.  
  45.   /* documentation is in ftoutln.h */
  46.  
  47.   FT_EXPORT_DEF( FT_Error )
  48.   FT_Outline_Decompose( FT_Outline*              outline,
  49.                         const FT_Outline_Funcs*  interface,
  50.                         void*                    user )
  51.   {
  52. #undef SCALED
  53. #define SCALED( x )  ( ( (x) << shift ) - delta )
  54.  
  55.     FT_Vector   v_last;
  56.     FT_Vector   v_control;
  57.     FT_Vector   v_start;
  58.  
  59.     FT_Vector*  point;
  60.     FT_Vector*  limit;
  61.     char*       tags;
  62.  
  63.     FT_Error    error;
  64.  
  65.     FT_Int   n;         /* index of contour in outline     */
  66.     FT_UInt  first;     /* index of first point in contour */
  67.     FT_Int   tag;       /* current point's state           */
  68.  
  69.     FT_Int   shift;
  70.     FT_Pos   delta;
  71.  
  72.  
  73.     if ( !outline || !interface )
  74.       return FT_Err_Invalid_Argument;
  75.  
  76.     shift = interface->shift;
  77.     delta = interface->delta;
  78.     first = 0;
  79.  
  80.     for ( n = 0; n < outline->n_contours; n++ )
  81.     {
  82.       FT_Int  last;  /* index of last point in contour */
  83.  
  84.  
  85.       last  = outline->contours[n];
  86.       limit = outline->points + last;
  87.  
  88.       v_start = outline->points[first];
  89.       v_last  = outline->points[last];
  90.  
  91.       v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
  92.       v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
  93.  
  94.       v_control = v_start;
  95.  
  96.       point = outline->points + first;
  97.       tags  = outline->tags  + first;
  98.       tag   = FT_CURVE_TAG( tags[0] );
  99.  
  100.       /* A contour cannot start with a cubic control point! */
  101.       if ( tag == FT_Curve_Tag_Cubic )
  102.         goto Invalid_Outline;
  103.  
  104.       /* check first point to determine origin */
  105.       if ( tag == FT_Curve_Tag_Conic )
  106.       {
  107.         /* first point is conic control.  Yes, this happens. */
  108.         if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
  109.         {
  110.           /* start at last point if it is on the curve */
  111.           v_start = v_last;
  112.           limit--;
  113.         }
  114.         else
  115.         {
  116.           /* if both first and last points are conic,         */
  117.           /* start at their middle and record its position    */
  118.           /* for closure                                      */
  119.           v_start.x = ( v_start.x + v_last.x ) / 2;
  120.           v_start.y = ( v_start.y + v_last.y ) / 2;
  121.  
  122.           v_last = v_start;
  123.         }
  124.         point--;
  125.         tags--;
  126.       }
  127.  
  128.       error = interface->move_to( &v_start, user );
  129.       if ( error )
  130.         goto Exit;
  131.  
  132.       while ( point < limit )
  133.       {
  134.         point++;
  135.         tags++;
  136.  
  137.         tag = FT_CURVE_TAG( tags[0] );
  138.         switch ( tag )
  139.         {
  140.         case FT_Curve_Tag_On:  /* emit a single line_to */
  141.           {
  142.             FT_Vector  vec;
  143.  
  144.  
  145.             vec.x = SCALED( point->x );
  146.             vec.y = SCALED( point->y );
  147.  
  148.             error = interface->line_to( &vec, user );
  149.             if ( error )
  150.               goto Exit;
  151.             continue;
  152.           }
  153.  
  154.         case FT_Curve_Tag_Conic:  /* consume conic arcs */
  155.           v_control.x = SCALED( point->x );
  156.           v_control.y = SCALED( point->y );
  157.  
  158.         Do_Conic:
  159.           if ( point < limit )
  160.           {
  161.             FT_Vector  vec;
  162.             FT_Vector  v_middle;
  163.  
  164.  
  165.             point++;
  166.             tags++;
  167.             tag = FT_CURVE_TAG( tags[0] );
  168.  
  169.             vec.x = SCALED( point->x );
  170.             vec.y = SCALED( point->y );
  171.  
  172.             if ( tag == FT_Curve_Tag_On )
  173.             {
  174.               error = interface->conic_to( &v_control, &vec, user );
  175.               if ( error )
  176.                 goto Exit;
  177.               continue;
  178.             }
  179.  
  180.             if ( tag != FT_Curve_Tag_Conic )
  181.               goto Invalid_Outline;
  182.  
  183.             v_middle.x = ( v_control.x + vec.x ) / 2;
  184.             v_middle.y = ( v_control.y + vec.y ) / 2;
  185.  
  186.             error = interface->conic_to( &v_control, &v_middle, user );
  187.             if ( error )
  188.               goto Exit;
  189.  
  190.             v_control = vec;
  191.             goto Do_Conic;
  192.           }
  193.  
  194.           error = interface->conic_to( &v_control, &v_start, user );
  195.           goto Close;
  196.  
  197.         default:  /* FT_Curve_Tag_Cubic */
  198.           {
  199.             FT_Vector  vec1, vec2;
  200.  
  201.  
  202.             if ( point + 1 > limit                             ||
  203.                  FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
  204.               goto Invalid_Outline;
  205.  
  206.             point += 2;
  207.             tags  += 2;
  208.  
  209.             vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
  210.             vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
  211.  
  212.             if ( point <= limit )
  213.             {
  214.               FT_Vector  vec;
  215.  
  216.  
  217.               vec.x = SCALED( point->x );
  218.               vec.y = SCALED( point->y );
  219.  
  220.               error = interface->cubic_to( &vec1, &vec2, &vec, user );
  221.               if ( error )
  222.                 goto Exit;
  223.               continue;
  224.             }
  225.  
  226.             error = interface->cubic_to( &vec1, &vec2, &v_start, user );
  227.             goto Close;
  228.           }
  229.         }
  230.       }
  231.  
  232.       /* close the contour with a line segment */
  233.       error = interface->line_to( &v_start, user );
  234.  
  235.     Close:
  236.       if ( error )
  237.         goto Exit;
  238.  
  239.       first = last + 1;
  240.     }
  241.  
  242.     return 0;
  243.  
  244.   Exit:
  245.     return error;
  246.  
  247.   Invalid_Outline:
  248.     return FT_Err_Invalid_Outline;
  249.   }
  250.  
  251.  
  252.   FT_EXPORT_DEF( FT_Error )
  253.   FT_Outline_New_Internal( FT_Memory    memory,
  254.                            FT_UInt      numPoints,
  255.                            FT_Int       numContours,
  256.                            FT_Outline  *anoutline )
  257.   {
  258.     FT_Error  error;
  259.  
  260.  
  261.     if ( !anoutline || !memory )
  262.       return FT_Err_Invalid_Argument;
  263.  
  264.     *anoutline = null_outline;
  265.  
  266.     if ( ALLOC_ARRAY( anoutline->points,   numPoints * 2L, FT_Pos    ) ||
  267.          ALLOC_ARRAY( anoutline->tags,     numPoints,      FT_Byte   ) ||
  268.          ALLOC_ARRAY( anoutline->contours, numContours,    FT_UShort ) )
  269.       goto Fail;
  270.  
  271.     anoutline->n_points    = (FT_UShort)numPoints;
  272.     anoutline->n_contours  = (FT_Short)numContours;
  273.     anoutline->flags      |= ft_outline_owner;
  274.  
  275.     return FT_Err_Ok;
  276.  
  277.   Fail:
  278.     anoutline->flags |= ft_outline_owner;
  279.     FT_Outline_Done_Internal( memory, anoutline );
  280.  
  281.     return error;
  282.   }
  283.  
  284.  
  285.   /* documentation is in ftoutln.h */
  286.  
  287.   FT_EXPORT_DEF( FT_Error )
  288.   FT_Outline_New( FT_Library   library,
  289.                   FT_UInt      numPoints,
  290.                   FT_Int       numContours,
  291.                   FT_Outline  *anoutline )
  292.   {
  293.     if ( !library )
  294.       return FT_Err_Invalid_Library_Handle;
  295.  
  296.     return FT_Outline_New_Internal( library->memory, numPoints,
  297.                                     numContours, anoutline );
  298.   }
  299.  
  300.  
  301.   /* documentation is in ftoutln.h */
  302.  
  303.   FT_EXPORT_DEF( FT_Error )
  304.   FT_Outline_Check( FT_Outline*  outline )
  305.   {
  306.     if ( outline )
  307.     {
  308.       FT_Int  n_points   = outline->n_points;
  309.       FT_Int  n_contours = outline->n_contours;
  310.       FT_Int  end0, end;
  311.       FT_Int  n;
  312.  
  313.  
  314.       /* empty glyph? */
  315.       if ( n_points == 0 && n_contours == 0 )
  316.         return 0;
  317.  
  318.       /* check point and contour counts */
  319.       if ( n_points <= 0 || n_contours <= 0 )
  320.         goto Bad;
  321.  
  322.       end0 = end = -1;
  323.       for ( n = 0; n < n_contours; n++ )
  324.       {
  325.         end = outline->contours[n];
  326.  
  327.         /* note that we don't accept empty contours */
  328.         if ( end <= end0 || end >= n_points )
  329.           goto Bad;
  330.  
  331.         end0 = end;
  332.       }
  333.  
  334.       if ( end != n_points - 1 )
  335.         goto Bad;
  336.  
  337.       /* XXX: check the that array */
  338.       return 0;
  339.     }
  340.  
  341.   Bad:
  342.     return FT_Err_Invalid_Argument;
  343.   }
  344.  
  345.  
  346.   /* documentation is in ftoutln.h */
  347.  
  348.   FT_EXPORT_DEF( FT_Error )
  349.   FT_Outline_Copy( FT_Outline*  source,
  350.                    FT_Outline  *target )
  351.   {
  352.     FT_Int  is_owner;
  353.  
  354.  
  355.     if ( !source            || !target            ||
  356.          source->n_points   != target->n_points   ||
  357.          source->n_contours != target->n_contours )
  358.       return FT_Err_Invalid_Argument;
  359.  
  360.     MEM_Copy( target->points, source->points,
  361.               source->n_points * sizeof ( FT_Vector ) );
  362.  
  363.     MEM_Copy( target->tags, source->tags,
  364.               source->n_points * sizeof ( FT_Byte ) );
  365.  
  366.     MEM_Copy( target->contours, source->contours,
  367.               source->n_contours * sizeof ( FT_Short ) );
  368.  
  369.     /* copy all flags, except the `ft_outline_owner' one */
  370.     is_owner      = target->flags & ft_outline_owner;
  371.     target->flags = source->flags;
  372.  
  373.     target->flags &= ~ft_outline_owner;
  374.     target->flags |= is_owner;
  375.  
  376.     return FT_Err_Ok;
  377.   }
  378.  
  379.  
  380.   FT_EXPORT_DEF( FT_Error )
  381.   FT_Outline_Done_Internal( FT_Memory    memory,
  382.                             FT_Outline*  outline )
  383.   {
  384.     if ( outline )
  385.     {
  386.       if ( outline->flags & ft_outline_owner )
  387.       {
  388.         FREE( outline->points   );
  389.         FREE( outline->tags     );
  390.         FREE( outline->contours );
  391.       }
  392.       *outline = null_outline;
  393.  
  394.       return FT_Err_Ok;
  395.     }
  396.     else
  397.       return FT_Err_Invalid_Argument;
  398.   }
  399.  
  400.  
  401.   /* documentation is in ftoutln.h */
  402.  
  403.   FT_EXPORT_DEF( FT_Error )
  404.   FT_Outline_Done( FT_Library   library,
  405.                    FT_Outline*  outline )
  406.   {
  407.     /* check for valid `outline' in FT_Outline_Done_Internal() */
  408.  
  409.     if ( !library )
  410.       return FT_Err_Invalid_Library_Handle;
  411.  
  412.     return FT_Outline_Done_Internal( library->memory, outline );
  413.   }
  414.  
  415.  
  416.   /* documentation is in ftoutln.h */
  417.  
  418.   FT_EXPORT_DEF( void )
  419.   FT_Outline_Get_CBox( FT_Outline*  outline,
  420.                        FT_BBox     *acbox )
  421.   {
  422.     FT_Pos  xMin, yMin, xMax, yMax;
  423.  
  424.  
  425.     if ( outline && acbox )
  426.     {
  427.       if ( outline->n_points == 0 )
  428.       {
  429.         xMin = 0;
  430.         yMin = 0;
  431.         xMax = 0;
  432.         yMax = 0;
  433.       }
  434.       else
  435.       {
  436.         FT_Vector*  vec   = outline->points;
  437.         FT_Vector*  limit = vec + outline->n_points;
  438.  
  439.  
  440.         xMin = xMax = vec->x;
  441.         yMin = yMax = vec->y;
  442.         vec++;
  443.  
  444.         for ( ; vec < limit; vec++ )
  445.         {
  446.           FT_Pos  x, y;
  447.  
  448.  
  449.           x = vec->x;
  450.           if ( x < xMin ) xMin = x;
  451.           if ( x > xMax ) xMax = x;
  452.  
  453.           y = vec->y;
  454.           if ( y < yMin ) yMin = y;
  455.           if ( y > yMax ) yMax = y;
  456.         }
  457.       }
  458.       acbox->xMin = xMin;
  459.       acbox->xMax = xMax;
  460.       acbox->yMin = yMin;
  461.       acbox->yMax = yMax;
  462.     }
  463.   }
  464.  
  465.  
  466.   /* documentation is in ftoutln.h */
  467.  
  468.   FT_EXPORT_DEF( void )
  469.   FT_Outline_Translate( FT_Outline*  outline,
  470.                         FT_Pos       xOffset,
  471.                         FT_Pos       yOffset )
  472.   {
  473.     FT_UShort   n;
  474.     FT_Vector*  vec = outline->points;
  475.  
  476.  
  477.     for ( n = 0; n < outline->n_points; n++ )
  478.     {
  479.       vec->x += xOffset;
  480.       vec->y += yOffset;
  481.       vec++;
  482.     }
  483.   }
  484.  
  485.  
  486.   /* documentation is in ftoutln.h */
  487.  
  488.   FT_EXPORT_DEF( void )
  489.   FT_Outline_Reverse( FT_Outline*  outline )
  490.   {
  491.     FT_UShort  n;
  492.     FT_Int     first, last;
  493.  
  494.  
  495.     first = 0;
  496.  
  497.     for ( n = 0; n < outline->n_contours; n++ )
  498.     {
  499.       last  = outline->contours[n];
  500.  
  501.       /* reverse point table */
  502.       {
  503.         FT_Vector*  p = outline->points + first;
  504.         FT_Vector*  q = outline->points + last;
  505.         FT_Vector   swap;
  506.  
  507.  
  508.         while ( p < q )
  509.         {
  510.           swap = *p;
  511.           *p   = *q;
  512.           *q   = swap;
  513.           p++;
  514.           q--;
  515.         }
  516.       }
  517.  
  518.       /* reverse tags table */
  519.       {
  520.         char*  p = outline->tags + first;
  521.         char*  q = outline->tags + last;
  522.         char   swap;
  523.  
  524.  
  525.         while ( p < q )
  526.         {
  527.           swap = *p;
  528.           *p   = *q;
  529.           *q   = swap;
  530.           p++;
  531.           q--;
  532.         }
  533.       }
  534.  
  535.       first = last + 1;
  536.     }
  537.  
  538.     outline->flags ^= ft_outline_reverse_fill;
  539.   }
  540.  
  541.  
  542.   /* documentation is in ftoutln.h */
  543.  
  544.   FT_EXPORT_DEF( FT_Error )
  545.   FT_Outline_Render( FT_Library         library,
  546.                      FT_Outline*        outline,
  547.                      FT_Raster_Params*  params )
  548.   {
  549.     FT_Error     error;
  550.     FT_Bool      update = 0;
  551.     FT_Renderer  renderer;
  552.     FT_ListNode  node;
  553.  
  554.  
  555.     if ( !library )
  556.       return FT_Err_Invalid_Library_Handle;
  557.  
  558.     if ( !params )
  559.       return FT_Err_Invalid_Argument;
  560.  
  561.     renderer = library->cur_renderer;
  562.     node     = library->renderers.head;
  563.  
  564.     params->source = (void*)outline;
  565.  
  566.     error = FT_Err_Cannot_Render_Glyph;
  567.     while ( renderer )
  568.     {
  569.       error = renderer->raster_render( renderer->raster, params );
  570.       if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
  571.         break;
  572.  
  573.       /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
  574.       /* is unsupported by the current renderer for this glyph image */
  575.       /* format                                                      */
  576.  
  577.       /* now, look for another renderer that supports the same */
  578.       /* format                                                */
  579.       renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline,
  580.                                      &node );
  581.       update   = 1;
  582.     }
  583.  
  584.     /* if we changed the current renderer for the glyph image format */
  585.     /* we need to select it as the next current one                  */
  586.     if ( !error && update && renderer )
  587.       FT_Set_Renderer( library, renderer, 0, 0 );
  588.  
  589.     return error;
  590.   }
  591.  
  592.  
  593.   /* documentation is in ftoutln.h */
  594.  
  595.   FT_EXPORT_DEF( FT_Error )
  596.   FT_Outline_Get_Bitmap( FT_Library   library,
  597.                          FT_Outline*  outline,
  598.                          FT_Bitmap   *abitmap )
  599.   {
  600.     FT_Raster_Params  params;
  601.  
  602.  
  603.     if ( !abitmap )
  604.       return FT_Err_Invalid_Argument;
  605.  
  606.     /* other checks are delayed to FT_Outline_Render() */
  607.  
  608.     params.target = abitmap;
  609.     params.flags  = 0;
  610.  
  611.     if ( abitmap->pixel_mode == ft_pixel_mode_grays )
  612.       params.flags |= ft_raster_flag_aa;
  613.  
  614.     return FT_Outline_Render( library, outline, ¶ms );
  615.   }
  616.  
  617.  
  618.   /* documentation is in ftoutln.h */
  619.  
  620.   FT_EXPORT_DEF( void )
  621.   FT_Vector_Transform( FT_Vector*  vector,
  622.                        FT_Matrix*  matrix )
  623.   {
  624.     FT_Pos xz, yz;
  625.  
  626.  
  627.     if ( !vector || !matrix )
  628.       return;
  629.  
  630.     xz = FT_MulFix( vector->x, matrix->xx ) +
  631.          FT_MulFix( vector->y, matrix->xy );
  632.  
  633.     yz = FT_MulFix( vector->x, matrix->yx ) +
  634.          FT_MulFix( vector->y, matrix->yy );
  635.  
  636.     vector->x = xz;
  637.     vector->y = yz;
  638.   }
  639.  
  640.  
  641.   /* documentation is in ftoutln.h */
  642.  
  643.   FT_EXPORT_DEF( void )
  644.   FT_Outline_Transform( FT_Outline*  outline,
  645.                         FT_Matrix*   matrix )
  646.   {
  647.     FT_Vector*  vec = outline->points;
  648.     FT_Vector*  limit = vec + outline->n_points;
  649.  
  650.  
  651.     for ( ; vec < limit; vec++ )
  652.       FT_Vector_Transform( vec, matrix );
  653.   }
  654.  
  655.  
  656. /* END */
  657.